package com.google.code.sms.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ParameterizableViewController;

import com.google.code.sms.Logger;
import com.google.code.sms.domain.MediaElement;
import com.google.code.sms.domain.MediaFolder;
import com.google.code.sms.domain.MediaElementIndex;
import com.google.code.sms.service.MediaElementService;
import com.google.code.sms.service.MediaScannerService;
import com.google.code.sms.service.MediaElementIndexService;
import com.google.code.sms.service.PlayerService;
import com.google.code.sms.service.SecurityService;
import com.google.code.sms.service.SettingsService;

/**
 * Controller for the left index frame.
 *
 * @author Sindre Mehus
 */
public class LeftController extends ParameterizableViewController {

    private static final Logger LOG = Logger.getLogger("LeftController");
    // Update this time if you want to force a refresh in clients.
    private static final Calendar LAST_COMPATIBILITY_TIME = Calendar.getInstance();

    static {
        LAST_COMPATIBILITY_TIME.set(2012, Calendar.MARCH, 6, 0, 0, 0);
        LAST_COMPATIBILITY_TIME.set(Calendar.MILLISECOND, 0);
    }
    private MediaScannerService mediaScannerService;
    private SettingsService settingsService;
    private SecurityService securityService;
    private MediaElementService mediaElementService;
    private MediaElementIndexService mediaElementIndexService;
    private PlayerService playerService;

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception
    {
        Map<String, Object> map = new HashMap<>();

        String username = securityService.getCurrentUsername(request);
        List<MediaFolder> allMediaFolders = settingsService.getAllMediaFolders();
        
        MediaFolder selectedMediaFolder = null;
        if (request.getParameter("mediaFolderId") != null)
        {
            selectedMediaFolder = settingsService.getMediaFolderById(Integer.parseInt(request.getParameter("mediaFolderId")));
        }
        
        List<MediaFolder> mediaFoldersToUse = selectedMediaFolder == null ? allMediaFolders : Arrays.asList(selectedMediaFolder);
        MediaFolderContent mediaFolderContent = getMediaFolderContent(mediaFoldersToUse);

        map.put("player", playerService.getPlayer(request, response));
        map.put("scanning", mediaScannerService.isScanning());
        map.put("mediaFolders", allMediaFolders);
        map.put("selectedMediaFolder", selectedMediaFolder);
        map.put("organizeByFolderStructure", settingsService.isOrganizeByFolderStructure());
        map.put("indexedMediaElements", mediaFolderContent.getIndexedMediaElements());
        map.put("singleMediaElements", mediaFolderContent.getSingleMediaElements());
        map.put("indexes", mediaFolderContent.getIndexedMediaElements().keySet());
        map.put("user", securityService.getCurrentUser(request));

        ModelAndView result = super.handleRequestInternal(request, response);
        result.addObject("model", map);
        return result;
    }

    protected List<MediaElement> getSingleMediaElements(List<MediaFolder> folders) throws IOException {
        List<MediaElement> result = new ArrayList<>();
        for (MediaFolder folder : folders) {
            result.addAll(mediaElementService.getChildrenOf(folder.getPath(), true, true, false, true));
        }
        return result;
    }

    public MediaFolderContent getMediaFolderContent(List<MediaFolder> mediaFoldersToUse) throws Exception {
        SortedMap<MediaElementIndex, SortedSet<MediaElementIndex.SortableMediaElementWithMediaElements>> indexedMediaElements = mediaElementIndexService.getIndexedMediaElementsFromMediaFolders(mediaFoldersToUse);
        List<MediaElement> singleMediaElements = getSingleMediaElements(mediaFoldersToUse);
        return new MediaFolderContent(indexedMediaElements, singleMediaElements);
    }

    public void setMediaScannerService(MediaScannerService mediaScannerService) {
        this.mediaScannerService = mediaScannerService;
    }

    public void setSettingsService(SettingsService settingsService) {
        this.settingsService = settingsService;
    }

    public void setSecurityService(SecurityService securityService) {
        this.securityService = securityService;
    }

    public void setMediaElementService(MediaElementService mediaElementService) {
        this.mediaElementService = mediaElementService;
    }

    public void setMediaElementIndexService(MediaElementIndexService mediaElementIndexService) {
        this.mediaElementIndexService = mediaElementIndexService;
    }

    public void setPlayerService(PlayerService playerService) {
        this.playerService = playerService;
    }

    public static class MediaFolderContent {

        private final SortedMap<MediaElementIndex, SortedSet<MediaElementIndex.SortableMediaElementWithMediaElements>> indexedMediaElements;
        private final List<MediaElement> singleMediaElements;

        public MediaFolderContent(SortedMap<MediaElementIndex, SortedSet<MediaElementIndex.SortableMediaElementWithMediaElements>> indexedMediaElements, List<MediaElement> singleMediaElements) {
            this.indexedMediaElements = indexedMediaElements;
            this.singleMediaElements = singleMediaElements;
        }

        public SortedMap<MediaElementIndex, SortedSet<MediaElementIndex.SortableMediaElementWithMediaElements>> getIndexedMediaElements() {
            return indexedMediaElements;
        }

        public List<MediaElement> getSingleMediaElements() {
            return singleMediaElements;
        }
    }
}
